import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import org.jdom.*;
import org.jdom.input.*;
import org.jdom.transform.*;
import org.jdom.output.*;
import org.jdom.filter.*;
import java.net.*;
import java.util.*;
import net.sf.saxon.*;

public class Edit extends HttpServlet {
    Document servers = new Document();
    public void doGet(HttpServletRequest request, 
		      HttpServletResponse response)
	throws IOException, ServletException {
	PrintWriter out = response.getWriter();
	response.setContentType("text/html");
	String word = htmlEscape(request.getParameter("word"));
	String wiki = htmlEscape(request.getParameter("wiki"));
	if(wiki == null || wiki.equals("")){
	    throw new RuntimeException("Wiki parameter is needed when trying to edit a Wiki document!");
	}
	Document transDoc = new Document();
	try{
	    URL servURL = getServerURL(wiki);
	    SAXBuilder b = new SAXBuilder();
	    Document doc = new Document();
	    try{
		doc = b.build(servURL + "?word=" + word);
	    }
	    catch(Exception e){
		Namespace wikiNS = Namespace.getNamespace("http://daimi.au.dk/dWebTek/WikiXML");
		Element root = new Element("wiki",wikiNS);
		root.setAttribute("name",word);
		Element test = new Element("word",wikiNS);
		test.addContent("Skriv indholdet af din wiki side om "+ word + " her.");
		root.addContent(test);
		doc = new Document(root);
		XMLOutputter testOut = new XMLOutputter();
	    }
	    File styleXML = new File("webapps/Wiki/WEB-INF/source/WikiXML2Txt.xsl");
	    transDoc = getXMLDocument(doc,styleXML);
	    changeForm(transDoc,wiki);
	    changeLink(transDoc,wiki,word);
	    setAllWordlinks(transDoc,b,wiki);
	    showWikiServer(transDoc,wiki,out);

	}
	catch(Exception e){
	    out.print(e);
	    System.err.print(e);
	}
	finally{
	    XMLOutputter outputter = new XMLOutputter();
	    try{
		outputter.output(transDoc,out);
	    }
	catch(Exception e){
	    
	}
	    out.close();
	}
    }
    
    public void doPost(HttpServletRequest request,
		       HttpServletResponse response)
	throws IOException, ServletException {
	PrintWriter out = response.getWriter();
	Txt2WikiXML parser = new Txt2WikiXML(new StringReader(htmlEscape(request.getParameter("content"))));
	Document doc = parser.parseWiki();
	String word = htmlEscape(request.getParameter("word"));
	String wiki = htmlEscape(request.getParameter("wiki"));
	doc.getRootElement().setAttribute("name",word);
	XMLOutputter outputter = new XMLOutputter();
	try{
	    URL postURL = new URL(getServerURL(wiki) + "?word=" + word);
	    out.print(postURL);
	    HttpURLConnection con = (HttpURLConnection)postURL.openConnection();
	    con.setRequestMethod("PUT");
	    con.setDoOutput(true);
	    con.setRequestProperty("ContentType","text/xml");
	    try{
		outputter.output(doc,con.getOutputStream());
		int codeI = con.getResponseCode();
 		if(199 < codeI && codeI < 299){
		    response.sendRedirect("Read?wiki=" + wiki + "&word="+word);
		    out.print("du fik den rigtige errorCode");
		}
		response.setContentType("text/html");
		InputStream err = con.getErrorStream();
		int c;
		if(err != null){
		    while((c=err.read())!=-1) {
			out.print(new Character((char)c));
		    }
		}
	    }
	    catch(Exception e){
		out.print(e);
	    }

	}
	catch(Exception e){
	    out.print(e);	    
	}
    }

    private Document getXMLDocument(Document doc, File xslFile) throws Exception {
	Transformer t = TransformerFactory.newInstance().newTransformer(new StreamSource(xslFile));
	JDOMSource inT = new JDOMSource(doc);
	JDOMResult outT = new JDOMResult();
	t.transform(inT,outT);
	return outT.getDocument();	
    }

    private URL getServerURL(String wiki) throws Exception{
	SAXBuilder b = new SAXBuilder();
	Document servDoc = b.build(new URL("http://kalashnikov.daimi.au.dk:8888/Wiki/Meta"));
	XMLOutputter xmlOutputter = new XMLOutputter();
	String urlString = "http://camel26.daimi.au.dk:8128/Wiki/Server";
	Element rootElement = new Element("wiki");
	Element servRoot = servDoc.getRootElement();
	Iterator i = servDoc.getRootElement().getDescendants(new ElementFilter("server"));
	/**
	 * RootElement:
	 * <wiki>
	 *   <server host="" name="" port="">
	 *   <server host="" name="" port="">
	 *   . . . etc. en for hver server der matcher navnet. 
	 *   Hvis der er flere der matcher returneres den sidste.
	 */
	while(i.hasNext()){
	    Element ele = (Element)i.next();
	    if(ele.getAttributeValue("name").equals(wiki)){
		Element tmpServ = new Element("server");
		tmpServ.setAttribute("name",ele.getAttributeValue("name"));		
		tmpServ.setAttribute("host",ele.getAttributeValue("host"));		
		tmpServ.setAttribute("port",ele.getAttributeValue("port"));
		rootElement.addContent(tmpServ);
		urlString = "http://" + ele.getAttributeValue("host") + ":" + ele.getAttributeValue("port") + "/Wiki/Server";
	    }
	}
	this.servers = servRoot.getDocument();
	return new URL(urlString);
    }

private void changeForm(Document d,String wiki){
	ArrayList<Element> eleList = new ArrayList<Element>();
	Iterator i = d.getRootElement().getDescendants(new ElementFilter("form"));    
	while(i.hasNext()){
	    Element ele = (Element)i.next();
	    if(ele.getAttributeValue("method").equals("POST")){
		eleList.add(ele);
	    }
	}
	i = eleList.iterator();
	while(i.hasNext()){
	    Element ele = (Element)i.next();
	    Element wikiName = new Element("input");		    
	    wikiName.setAttribute("type","hidden");
	    wikiName.setAttribute("value",wiki);
	    wikiName.setAttribute("name","wiki");
	    ele.addContent(wikiName);
	}
    }

    private void changeLink(Document d,String wiki, String word){
	ArrayList<Element> eleList = new ArrayList<Element>();
	Iterator i = d.getRootElement().getDescendants(new ElementFilter("a"));  
	while(i.hasNext()){
	    Element ele = (Element)i.next();
	    if(ele.getAttributeValue("name") != null && 
	       ele.getAttributeValue("name").equals("test")){
		eleList.add(ele);
		
	    }
	}
	i = eleList.iterator();
	while(i.hasNext()){
	    Element ele = (Element)i.next();
	    ele.setAttribute("href","Read?wiki="+wiki+"&word="+word);
	    ele.addContent("Read");
	}
    }

    private void getServersSelect(Document d){
	Iterator i = d.getRootElement().getDescendants(new ElementFilter("select"));  
	Element ele = new Element("option");
	while(i.hasNext()){
	    ele = (Element)i.next();	    
	}
	Iterator j = servers.getDescendants(new ElementFilter("server"));
	while(j.hasNext()){
	    Element servEle = (Element)j.next();
	    Element option = new Element("option");
	    option.setAttribute("value",servEle.getAttributeValue("name"));
	    option.addContent(servEle.getAttributeValue("name"));
	    ele.addContent(option);
	}
    }

    private void setAllWordlinks(Document d,SAXBuilder b,String wiki) throws Exception{
	Iterator i = d.getRootElement().getDescendants(new ElementFilter("div"));
	Element ele = new Element("div");
	while(i.hasNext()){
	    Element test = (Element)i.next();
	    if(test.getAttributeValue("name") != null && test.getAttributeValue("name").equals("wordlist")){
		ele = test; 
	    }
	}
	Document words = b.build(getServerURL(wiki));
	Iterator j = words.getDescendants(new ElementFilter("word"));
	Element ul = new Element("ul");
	while(j.hasNext()){
	    Element wordEle = (Element)j.next();
	    Element li = new Element("li");
	    Element link = new Element("a");
	    link.setAttribute("href","Read?wiki=" + wiki + "&word=" +wordEle.getText());
		    link.addContent(wordEle.getText());
		    li.addContent(link);
		    ul.addContent(li);
	}
	ele.addContent(ul);
    }

    private void showWikiServer(Document d, String wiki,PrintWriter out){
	Iterator i = d.getRootElement().getDescendants(new ElementFilter("div"));  
	Element ele = new Element("div");
	while(i.hasNext()){
	    Element tempEle = (Element)i.next();
	    if(tempEle.getAttributeValue("name") != null && tempEle.getAttributeValue("name").equals("wikiserver")){
		ele = tempEle;
	    }
	}
	ele.addContent(wiki + "-");
    }

    private String htmlEscape(String s){
	if(s == null)
	    return null;
	StringBuffer b = new StringBuffer();
	for(int i= 0 ; i<s.length(); i++){
	    char c= s.charAt(i);
	    switch(c){
	    case '<': b.append("&lt;"); break;
	    case '>': b.append("&gt;"); break;
	    case '"': b.append("&quot;"); break;
	    case '\'': b.append("&apos;"); break;
	    case '&': b.append("&amp;"); break;
	    default : b.append(c);
	    }
	}
	return b.toString();
    }
}